1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import com.google.common.annotations.GwtCompatible;
20
21 import junit.framework.TestCase;
22
23 import java.util.Iterator;
24 import java.util.NoSuchElementException;
25
26
27
28
29
30
31 @SuppressWarnings("serial")
32 @GwtCompatible(emulated = true)
33
34 public class AbstractIteratorTest extends TestCase {
35
36 public void testDefaultBehaviorOfNextAndHasNext() {
37
38
39
40 Iterator<Integer> iter = new AbstractIterator<Integer>() {
41 private int rep;
42 @Override public Integer computeNext() {
43 switch (rep++) {
44 case 0:
45 return 0;
46 case 1:
47 return 1;
48 case 2:
49 return endOfData();
50 default:
51 fail("Should not have been invoked again");
52 return null;
53 }
54 }
55 };
56
57 assertTrue(iter.hasNext());
58 assertEquals(0, (int) iter.next());
59
60
61 assertTrue(iter.hasNext());
62 assertTrue(iter.hasNext());
63 assertTrue(iter.hasNext());
64 assertEquals(1, (int) iter.next());
65
66 assertFalse(iter.hasNext());
67
68
69 assertFalse(iter.hasNext());
70
71 try {
72 iter.next();
73 fail("no exception thrown");
74 } catch (NoSuchElementException expected) {
75 }
76 }
77
78 public void testDefaultBehaviorOfPeek() {
79
80
81
82
83 AbstractIterator<Integer> iter = new AbstractIterator<Integer>() {
84 private int rep;
85 @Override public Integer computeNext() {
86 switch (rep++) {
87 case 0:
88 return 0;
89 case 1:
90 return 1;
91 case 2:
92 return endOfData();
93 default:
94 fail("Should not have been invoked again");
95 return null;
96 }
97 }
98 };
99
100 assertEquals(0, (int) iter.peek());
101 assertEquals(0, (int) iter.peek());
102 assertTrue(iter.hasNext());
103 assertEquals(0, (int) iter.peek());
104 assertEquals(0, (int) iter.next());
105
106 assertEquals(1, (int) iter.peek());
107 assertEquals(1, (int) iter.next());
108
109 try {
110 iter.peek();
111 fail("peek() should throw NoSuchElementException at end");
112 } catch (NoSuchElementException expected) {
113 }
114
115 try {
116 iter.peek();
117 fail("peek() should continue to throw NoSuchElementException at end");
118 } catch (NoSuchElementException expected) {
119 }
120
121 try {
122 iter.next();
123 fail("next() should throw NoSuchElementException as usual");
124 } catch (NoSuchElementException expected) {
125 }
126
127 try {
128 iter.peek();
129 fail("peek() should still throw NoSuchElementException after next()");
130 } catch (NoSuchElementException expected) {
131 }
132 }
133
134 public void testDefaultBehaviorOfPeekForEmptyIteration() {
135
136 AbstractIterator<Integer> empty = new AbstractIterator<Integer>() {
137 private boolean alreadyCalledEndOfData;
138 @Override public Integer computeNext() {
139 if (alreadyCalledEndOfData) {
140 fail("Should not have been invoked again");
141 }
142 alreadyCalledEndOfData = true;
143 return endOfData();
144 }
145 };
146
147 try {
148 empty.peek();
149 fail("peek() should throw NoSuchElementException at end");
150 } catch (NoSuchElementException expected) {
151 }
152
153 try {
154 empty.peek();
155 fail("peek() should continue to throw NoSuchElementException at end");
156 } catch (NoSuchElementException expected) {
157 }
158 }
159
160 public void testSneakyThrow() throws Exception {
161 Iterator<Integer> iter = new AbstractIterator<Integer>() {
162 boolean haveBeenCalled;
163 @Override public Integer computeNext() {
164 if (haveBeenCalled) {
165 fail("Should not have been called again");
166 } else {
167 haveBeenCalled = true;
168 sneakyThrow(new SomeCheckedException());
169 }
170 return null;
171 }
172 };
173
174
175 try {
176 iter.hasNext();
177 fail("No exception thrown");
178 } catch (Exception e) {
179 if (!(e instanceof SomeCheckedException)) {
180 throw e;
181 }
182 }
183
184
185 try {
186 iter.hasNext();
187 fail("No exception thrown");
188 } catch (IllegalStateException expected) {
189 }
190 }
191
192 public void testException() {
193 final SomeUncheckedException exception = new SomeUncheckedException();
194 Iterator<Integer> iter = new AbstractIterator<Integer>() {
195 @Override public Integer computeNext() {
196 throw exception;
197 }
198 };
199
200
201 try {
202 iter.hasNext();
203 fail("No exception thrown");
204 } catch (SomeUncheckedException e) {
205 assertSame(exception, e);
206 }
207 }
208
209 public void testExceptionAfterEndOfData() {
210 Iterator<Integer> iter = new AbstractIterator<Integer>() {
211 @Override public Integer computeNext() {
212 endOfData();
213 throw new SomeUncheckedException();
214 }
215 };
216 try {
217 iter.hasNext();
218 fail("No exception thrown");
219 } catch (SomeUncheckedException expected) {
220 }
221 }
222
223 public void testCantRemove() {
224 Iterator<Integer> iter = new AbstractIterator<Integer>() {
225 boolean haveBeenCalled;
226 @Override public Integer computeNext() {
227 if (haveBeenCalled) {
228 endOfData();
229 }
230 haveBeenCalled = true;
231 return 0;
232 }
233 };
234
235 assertEquals(0, (int) iter.next());
236
237 try {
238 iter.remove();
239 fail("No exception thrown");
240 } catch (UnsupportedOperationException expected) {
241 }
242 }
243
244 public void testReentrantHasNext() {
245 Iterator<Integer> iter = new AbstractIterator<Integer>() {
246 @Override protected Integer computeNext() {
247 hasNext();
248 return null;
249 }
250 };
251 try {
252 iter.hasNext();
253 fail();
254 } catch (IllegalStateException expected) {
255 }
256 }
257
258
259
260
261
262
263
264
265 private static void sneakyThrow(Throwable t) {
266 class SneakyThrower<T extends Throwable> {
267 @SuppressWarnings("unchecked")
268 void throwIt(Throwable t) throws T {
269 throw (T) t;
270 }
271 }
272 new SneakyThrower<Error>().throwIt(t);
273 }
274
275 private static class SomeCheckedException extends Exception {
276 }
277
278 private static class SomeUncheckedException extends RuntimeException {
279 }
280 }
281